import os, sys, re, binascii, random

def gen_guid():
	guid = ''

	for i in range(16):
		guid += binascii.hexlify(chr(random.randint(0, 255))).upper()
	guid = guid[0:8] + '-' + guid[8:12] + '-' + guid[12:16] + '-' + \
			guid[16:20] + '-' + guid[20:32]
	return guid

def re_binary(expression, string):
	return expression.search(string) != None

def str_match(m):
	return m.string[m.start(0):m.end(0)] 

def update_solution(name, type, guid, solution):
	# Find solution guid
	solution_guid = ''
	library_guid = ''
	expr_guid = re.compile('[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}')
	for line in solution:
		result = expr_guid.search(line)
		if result != None:
			solution_guid = str_match(result)
			result2 = expr_guid.search(line[result.end():])
			library_guid = str_match(result2)
			break	
			
	expr_end_project = re.compile('EndProject')
	last_project_end_line = -1
	for line in range(len(solution)):
		if re_binary(expr_end_project, solution[line]):
			last_project_end_line = line
			
	last_guid_line = -1
	for line in range(len(solution)):
		if re_binary(expr_guid, solution[line]):
			last_guid_line = line

	project_path = 'samples\\' if type == 'sample' else	'apps\\'
	project_path += name + '\\' + name + '.vcproj'

	project_desc = []
	project_desc += ['Project("{' + solution_guid + '}") = "' + name + \
		'", "' + project_path + '", "{' + guid + '}"']
	project_desc += ['\tProjectSection(ProjectDependencies) = postProject']
	project_desc += ['\t\t{' + library_guid + '} = {' + library_guid + '}']
	project_desc += ['\tEndProjectSection']
	project_desc += ['EndProject']
	project_desc = [line + '\n' for line in project_desc] 

	# Make this smarter with re search&replace
	project_confs = []
	project_confs += ['\t\t{' + guid + '}.Debug|Win32.ActiveCfg = Debug|Win32']
	project_confs += ['\t\t{' + guid + '}.Debug|Win32.Build.0 = Debug|Win32']
	project_confs += ['\t\t{' + guid + '}.Release|Win32.ActiveCfg = Release|Win32']
	project_confs += ['\t\t{' + guid + '}.Release|Win32.Build.0 = Release|Win32']
	project_confs = [line + '\n' for line in project_confs]

	return solution[0:last_project_end_line+1] + project_desc +  \
		solution[last_project_end_line+1:last_guid_line+1] + \
		project_confs + solution[last_guid_line+1:]

def	make_project(name, guid, template):
	project = ''
	expr_name = re.compile('Empty')
	expr_guid = re.compile('[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}')
	result = expr_guid.search(template)	
	project = template.replace(str_match(result), guid)
	project = project.replace('Empty', name)

	return project	

def make_cpp(name, template):
	return template.replace('Empty', name).replace('empty', name.lower())

def make_dir(name, type):
	dir = 'samples\\' if type == 'sample' else 'apps\\'
	if os.access(dir + name, os.F_OK):
		os.chdir(dir + name)
		return
	if os.access('..\\' + dir + name, os.F_OK):
		os.chdir('..\\' + dir + name)
		return
	try:
		os.mkdir(dir + name)
		os.chdir(dir + name)
	except WindowsError:
		os.mkdir('..\\' + dir + name)
		os.chdir('..\\' + dir + name)

def find_files():
	try:
		solution = open('Cvekas.sln')
	except IOError:
		solution = open('..\\Cvekas.sln')
	sol = [line for line in solution]
	solution.close()

	try:
		project_templ = open('samples\\Empty\\Empty.vcproj')
	except IOError:
		project_templ = open('..\\samples\\Empty\\Empty.vcproj')
	proj = [line for line in project_templ]
	proj = ''.join(proj)
	project_templ.close()

	try:
		cpp_templ = open('samples\\Empty\\Empty.cpp')
	except IOError:
		cpp_templ = open('..\\samples\\Empty\\Empty.cpp')
	cpp = [line for line in cpp_templ]
	cpp = ''.join(cpp)
	cpp_templ.close()

	return (sol, proj, cpp)	

def write_new_files(name, guid, proj_templ, cpp_templ, do_cpp=True):
	proj = open(name + '.vcproj', 'w')
	proj.write(make_project(name, guid, proj_templ))
	proj.close()

	if do_cpp:
		cpp = open(name + '.cpp', 'w')
		cpp.write(make_cpp(name, cpp_templ))
		cpp.close()	

def new_project(name, type, do_cpp=True):
	solution, proj_templ, cpp_templ = find_files()
	guid = gen_guid()

	new_solution = update_solution(name, type, guid, solution)
	if os.access('Cvekas.sln', os.R_OK):
		sol = open('Cvekas.sln', 'w')
	else:
		sol = open('..\\Cvekas.sln', 'w')
	sol.write(''.join(new_solution))
	sol.close()

	make_dir(name, type)
	write_new_files(name, guid, proj_templ, cpp_templ, do_cpp)

if __name__ == '__main__':
	if len(sys.argv) != 3 and len(sys.argv) != 4:
		print 'Make new Cvekas project'
		print 'Example:'
		print 'tools\\new_project.py Name (sample|app) [nocpp]'
	else:
		do_cpp = len(sys.argv) == 4 and sys.argv[3] == 'nocpp' 
		do_cpp = not do_cpp
		name = sys.argv[1]
		type = sys.argv[2]
		new_project(name, type, do_cpp)
	
			
			
	
